package com.java.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Date;

import org.junit.jupiter.api.Test;

public class TestDriver {
	@Test
	public void test01() {
		/**
		 * 获取构造方法
		 */

		try {
			/**
			 * 使用constructor可以获取有参的，无参的构造方法
			 */
			// 获取一个类,记得添加泛型：即参数化
			Class<Student> c = (Class<Student>) Class.forName("com.java.reflection.Student");
			Constructor<Student> con = c.getDeclaredConstructor(String.class, String.class, double.class);
			Student stu0 = con.newInstance("张三", "男", 98.5);
			System.out.println(stu0);
			System.out.println("=========================");
			// 获取一个无参的构造方法
			Constructor<Student> con1 = c.getDeclaredConstructor();

			Student stu1 = con1.newInstance();
			stu1.setStuName("王五");
			System.out.println(stu1);
			/**
			 * 使用constructor可以获取有参的，无参的构造方法
			 */
			/**
			 * 使用class可以获取无参的构造方法
			 * 
			 */
			Student stu2 = c.newInstance();
			stu2.setStuName("李四");
			System.out.println(stu2);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	@Test
	public void test02() {
		/**
		 * 反射工具类：Method类
		 */

		try {
			// 获取一个类
			Class<Student> c1 = (Class<Student>) Class.forName("com.java.reflection.Student");
			// 创建一个学生的实例对象
			Student stu1=c1.newInstance();
			stu1.setStuName("李四");
			// 获取Method工具类
			// 第一个参数是方法名，第二个参数是该方法对应的形参类型的列表
			Method me = c1.getDeclaredMethod("doStuding", String.class, Date.class);
			// 获取权限
			me.setAccessible(true);
			// 使用Method类中的invoke方法，通过反射机制执行获取的方法对象
			/*
			 * invoke方法使用时，第一个参数是反射机制通过哪个实例对象去执行这个方法对象；
			 * 第二个是一个变长参数，需要和获取Method对象时所指定的形参列表保持对应关系； 返回值是方法对象执行的结果
			 */
			Object obj = me.invoke(stu1, "天津西青", new Date());
			System.out.println("输出信息为" + obj);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Test
	public void test03() {
		/**
		 * 反射工具类：Method类
		 */

		try {
			// 获取一个类
			Class<Student> c1 = (Class<Student>) Class.forName("com.java.reflection.Student");
			// 创建一个学生的实例对象
			Student stu1=c1.newInstance();
			stu1.setStuName("王五");
			// 获取Method工具类
			// 第一个参数是方法名，第二个参数是该方法对应的形参类型的列表
			Method me = c1.getDeclaredMethod("doStuding",  Date.class,String.class);
			// 获取权限
			me.setAccessible(true);
			// 使用Method类中的invoke方法，通过反射机制执行获取的方法对象
			/*
			 * invoke方法使用时，第一个参数是反射机制通过哪个实例对象去执行这个方法对象；
			 * 第二个是一个变长参数，需要和获取Method对象时所指定的形参列表保持对应关系； 返回值是方法对象执行的结果
			 */
			Object obj = me.invoke(stu1, new Date(), "天津西青");
			System.out.println("输出信息为" + obj);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
